/**
 * 权限控制工具模块
 * 
 * 本模块提供了一套完整的权限管理工具，用于实现系统中的访问控制、权限验证和路径匹配功能。
 * 它是权限控制系统的核心组件，支持灵活的权限模型和多种匹配策略。
 * 
 * 主要功能：
 * - 路径权限匹配（支持精确匹配、通配符和参数化路径）
 * - 权限验证（单项验证、与逻辑验证、或逻辑验证）
 * - 预定义权限组（简化常用权限集合的管理）
 * - 操作和资源类型定义（便于实现细粒度的权限控制）
 * 
 * 设计理念：
 * 采用RBAC（基于角色的访问控制）模型，将权限与角色关联，再将角色分配给用户。
 * 同时支持细粒度的基于资源和操作的权限控制。
 * 
 * @module utils/permission
 */

/**
 * 检查路径是否匹配权限
 * 支持三种匹配模式：
 * 1. 完全精确匹配 - 如 "/news/edit" 与 "/news/edit"
 * 2. 通配符匹配 - 如 "/news/*" 匹配 "/news/anything"
 * 3. 参数匹配 - 如 "/news/:id" 匹配 "/news/123"
 * 
 * @param path 当前路径，如用户实际访问的URL路径
 * @param permissionPath 权限路径，可以包含通配符或参数
 * @returns 是否匹配成功
 */
export const matchPath = (path: string, permissionPath: string): boolean => {
  // 完全匹配：两个路径完全一致
  if (path === permissionPath) {
    return true; // 路径完全相同，直接返回true
  }
  
  // 处理通配符：如 /news/* 匹配 /news/123, /news/edit 等
  if (permissionPath.endsWith('/*')) {
    const basePermissionPath = permissionPath.slice(0, -2); // 移除末尾的 /*
    return path.startsWith(basePermissionPath); // 检查是否以基础路径开头
  }
  
  // 处理路径参数：如 /news/:id 匹配 /news/123
  if (permissionPath.includes('/:')) {
    const permissionParts = permissionPath.split('/'); // 分割权限路径
    const pathParts = path.split('/'); // 分割实际路径
    
    // 如果段数不匹配，则不匹配（如 /news/:id 不匹配 /news/123/edit）
    if (permissionParts.length !== pathParts.length) {
      return false; // 路径段数不同，不匹配
    }
    
    // 逐段检查每个路径部分是否匹配
    return permissionParts.every((part, index) => {
      // 如果是参数部分（以:开头），则匹配任何值
      if (part.startsWith(':')) {
        return true; // 参数部分可以匹配任意值
      }
      // 否则精确匹配路径段
      return part === pathParts[index]; // 非参数部分需精确匹配
    });
  }
  
  return false; // 默认不匹配
};

/**
 * 检查用户是否具有指定权限集合中的任意一个权限
 * 实现"或"逻辑的权限验证，只需满足其中一项即可通过
 * 
 * 使用场景：
 * - 多种权限路径都可以访问同一资源
 * - 多个角色都可以执行同一操作
 * - 提供多种访问途径的功能
 * 
 * @param userRights 用户拥有的权限列表
 * @param requiredRights 需要的权限列表（满足一个即可）
 * @returns 是否有权限
 */
export const hasAnyRight = (userRights: string[], requiredRights: string[]): boolean => {
  // 空值检查，确保两个数组都存在
  if (!userRights || !requiredRights) {
    return false; // 如果任一参数为空，返回false
  }
  
  // 使用some方法检查是否有任一权限匹配
  return requiredRights.some(right => userRights.includes(right)); // 只要有一个权限匹配即返回true
};

/**
 * 检查用户是否具有指定权限集合中的所有权限
 * 实现"与"逻辑的权限验证，必须全部满足才能通过
 * 
 * 使用场景：
 * - 需要多项权限才能访问的敏感操作
 * - 复杂功能需要的组合权限检查
 * - 高安全性要求的管理功能
 * 
 * @param userRights 用户拥有的权限列表
 * @param requiredRights 需要的权限列表（必须全部满足）
 * @returns 是否有所有权限
 */
export const hasAllRights = (userRights: string[], requiredRights: string[]): boolean => {
  // 空值检查，确保两个数组都存在
  if (!userRights || !requiredRights) {
    return false; // 如果任一参数为空，返回false
  }
  
  // 使用every方法检查是否所有权限都匹配
  return requiredRights.every(right => userRights.includes(right)); // 所有权限都必须匹配
};

/**
 * 检查路径是否匹配用户的任意一个权限
 * 结合了路径匹配和权限验证功能
 * 
 * 使用场景：
 * - 路由访问控制
 * - 动态菜单构建
 * - 界面元素的条件渲染
 * 
 * @param path 当前路径
 * @param userRights 用户权限列表
 * @returns 是否有权限访问该路径
 */
export const checkPathPermission = (path: string, userRights: string[]): boolean => {
  // 空值检查，确保用户权限列表存在且不为空
  if (!userRights || userRights.length === 0) {
    return false; // 无权限或权限为空，返回false
  }
  
  // 检查用户的任一权限是否匹配当前路径
  return userRights.some(right => matchPath(path, right)); // 使用matchPath进行路径匹配检查
};

/**
 * 权限组定义
 * 预定义常用的权限组合，用于简化权限管理
 * 各组权限可直接使用，无需重复定义相关权限列表
 * 
 * 这些权限组对应系统中的主要功能模块，可以简化角色配置
 */
export const PermissionGroups = {
  // 内容管理权限组
  // 包含新闻添加、草稿箱和分类管理权限
  CONTENT_MANAGEMENT: [
    '/news-manage/add',      // 添加新闻
    '/news-manage/draft',    // 草稿箱管理 
    '/news-manage/category'  // 分类管理
  ],
  
  // 审核管理权限组
  // 包含审核和审核列表权限
  AUDIT_MANAGEMENT: [
    '/audit-manage/audit',   // 审核新闻 
    '/audit-manage/list'     // 审核列表
  ],
  
  // 发布管理权限组
  // 包含未发布、已发布和已下线三种状态的管理权限
  PUBLISH_MANAGEMENT: [
    '/publish-manage/unpublished',  // 待发布管理
    '/publish-manage/published',    // 已发布管理
    '/publish-manage/sunset'        // 已下线管理
  ],
  
  // 用户管理权限组
  // 包含用户列表管理权限
  USER_MANAGEMENT: [
    '/user-manage/list'      // 用户列表管理
  ],
  
  // 权限管理权限组
  // 包含角色列表和权限列表管理权限
  RIGHTS_MANAGEMENT: [
    '/right-manage/role/list',   // 角色列表管理
    '/right-manage/right/list'   // 权限列表管理
  ],
  
  // 超级管理员权限组
  // 拥有系统中所有权限（使用通配符表示）
  ADMIN: [
    '/*' // 所有权限（通配符匹配任意路径）
  ]
};

/**
 * 操作类型枚举
 * 定义系统中的基础操作类型，用于权限控制
 * 
 * 这些操作类型可以与资源类型组合，形成细粒度的权限控制
 * 例如：CREATE + NEWS = 创建新闻的权限
 */
export enum ActionType {
  CREATE = 'create',   // 创建操作 - 用于新建资源
  READ = 'read',       // 读取操作 - 用于查看资源
  UPDATE = 'update',   // 更新操作 - 用于修改资源
  DELETE = 'delete',   // 删除操作 - 用于删除资源
  PUBLISH = 'publish', // 发布操作 - 用于发布内容
  AUDIT = 'audit'      // 审核操作 - 用于审核内容
}

/**
 * 资源类型枚举
 * 定义系统中的主要资源类型，与操作类型结合使用
 * 
 * 资源类型与操作类型组合可以形成具体的权限项
 * 例如：NEWS + PUBLISH = 发布新闻的权限
 */
export enum ResourceType {
  NEWS = 'news',         // 新闻资源 - 系统的核心内容
  USER = 'user',         // 用户资源 - 系统用户
  ROLE = 'role',         // 角色资源 - 用户角色
  RIGHT = 'right',       // 权限资源 - 系统权限
  CATEGORY = 'category', // 分类资源 - 内容分类
  REGION = 'region'      // 区域资源 - 地区信息
}

// 导出所有工具函数和类型，便于统一引入使用
export default {
  // 路径匹配函数
  matchPath,             // 检查路径是否匹配权限
  
  // 权限检查函数
  hasAnyRight,           // 检查是否具有任意指定权限
  hasAllRights,          // 检查是否具有所有指定权限
  checkPathPermission,   // 检查路径是否有访问权限
  
  // 预定义常量
  PermissionGroups,      // 权限组定义
  ActionType,            // 操作类型枚举
  ResourceType           // 资源类型枚举
}; 